/*
	Author:	Alexey Serikov Kompaniets
	email:	kompadre@yandex.ru
	ICQ:	82514964
*/

#ifndef _AMEVER_H_
#define _AMEVER_H_

#ifndef _AME_INCLUDES
#define _AME_INCLUDES
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>	/* Needed for exit */
#include <unistd.h>	/* Needed for sleep/usleep */
#include <pthread.h>
#include <memory.h>
#include <errno.h>
#include <fcntl.h>	/* Needed for O_ defines */
#include <sys/types.h>	/* Needed for socket and select */
#include <sys/select.h>	/* Needed for select */
#include "chain.h"
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include <mysql.h>
#include "map.h"
#include "client.h"
#include "chain.h"
#include "char.h"
#include "mob.h"
#include "game.h"
#include "utils.h"
#endif

#define CLIENT(i) ((struct client *)s.fds[i].p)
#define CHAR(i) ((struct world_char *)i)
#define CHAR_RADIUS 18
#define MOB(i) ((struct world_mob *)i)

#define MAX_MAPS 24
#define MAX_SOCKET_DATA 255
#define MAX_FILEHANDLERS 24
#define MAX_CLIENTS 1023
#define MAX_HANDLERS MAX_FILEHANDLERS+MAX_CLIENTS
#define MAX_BAN_LIST 1023
#define IDLE_DISCONNECT 0xFFF
#define LOGFILE "flv-server.log"
#ifndef MAP_MAX_NAME
#define MAP_MAX_NAME 16
#endif

#define MAX_BYTES_SENT 255

#ifndef MAINLOOP_SLEEP
#define MAINLOOP_SLEEP 1
#endif

struct handler;

#ifndef BUF_SIZE
#define BUF_SIZE 1024 // Should be set like -DBUF_SIZE=XXXX in Makefile
#endif
#define MAX_BUF_SIZE (BUF_SIZE * 1024 * 1024)

struct buffer {
    unsigned char *data;
    unsigned size: 32;
	 unsigned head: 16;
    unsigned mark: 32;
    unsigned reallocNeeded: 1;
};

/* Core structures */
/** Client structure
This structure represents an output session.
*/
struct world_cell;

/** Server structure
This structure represents everything global in the application.
*/

struct server {
	struct {
		enum {
			FD_NONE = 0,
			FD_TIMEWAIT,
			FD_CLIENT_LISTENER,
			FD_LOGFILE,
			FD_CLIENT,
			FD_GM
		} type;
		unsigned idle: 16;
		void *p;
	} fds[MAX_HANDLERS];
	struct {
		unsigned short max_clients;
		unsigned short clients;
		unsigned short max_maps;
		unsigned short maps;
		unsigned shutting: 1;
	} status;
	struct {
		char input_ip[15];
		unsigned short input_port;
		char db_host[32];
		char db_user[32];
		char db_pass[32];
		char db_name[32];
	} config;
	struct {
 		struct world_map *p;
 		const char name[16];
 	} maps[MAX_MAPS];
	int client_listener, logfile; // Handlers
	unsigned int highest_fd, current_fd;
	struct timeval select_timeout;
	unsigned char buffy[255];
	unsigned int counter;
	MYSQL mysql_h;
	MYSQL_RES* 	sql_res ;
	MYSQL_ROW	sql_row ;
	char tmp_sql[512];
	lua_State *L;
	struct chain_set *clients;
	struct chain_set *chars;
	struct chain_set *ameQ;
	struct chain_set *freeNodes;
	unsigned int clock;
	int network_banList[MAX_BAN_LIST];
} extern s;

/* EFENCE stuff */
extern int EF_DISABLE_BANNER;
extern int EF_ALIGNMENT;
extern int EF_PROTECT_BELOW;
extern int EF_PROTECT_FREE;
extern int EF_ALLOW_MALLOC_0;
extern int EF_FREE_WIPES;

struct globalOptions  {
	const char *key;
	void *val;
	enum {
		T_VOD, // Nothing. Parsing this means the end of array
		// Numeric types (strtol, strtod)
		T_U16,
		T_U32,
		T_S16,
		T_S32,
		T_DBL,
		// String and *void (strcpy or memcpy)
		T_STR
	} type;
};

#define MAX_WALKPATH 48

struct walkpath_data {
	unsigned char path_len,path_pos,path_half;
	unsigned char path[MAX_WALKPATH];
	struct {
		unsigned X: 16;
		unsigned Y: 16;
	} key_cells[MAX_WALKPATH];
	int key_cells_count;
	struct chain_set *result_chain;
};

/* amever.c */
int server_init();
void server_shut(char *);
void server_getStatus();
int server_readConf();
int server_registerFD(int, int, void *);
int server_registerClient(int);
int server_registerMap(const char *, const char *);
void server_setMaxFD();
void server_setMaxFDAdded(int);
void server_unregister(int);
void server_signalInit();
inline void server_signalProc(int);
int server_sql_init();
void server_sql_shut();

/* utils.c */
void __attribute__ ((format (printf, 1, 2))) amelog(const char *fmt, ...);

/* buffer.c */
struct buffer *buffer_init (int);
int buffer_read (struct buffer *, int);
int buffer_readBytes(struct buffer*, int, int);
int buffer_write(struct buffer *, int);
void buffer_shut (struct buffer *);
int buffer_realloc (struct buffer *, int);
void buffer_cpy (struct buffer *, struct buffer *);
int buffer_move (struct buffer *, int);
void buffer_blank (struct buffer *me);

/* network.c */
int network_serve(char *, int);
int network_accept(int);
int network_shutdown(int);

/* lua_w.c */
int luaw_init(void);
void luaw_shut(void);
int luaw_testFunction(lua_State *);
int luaw_registerFunction(lua_State *, const char *, lua_CFunction);
inline void luaw_registerFunctions (lua_State *);
int luaw_testFunction (lua_State *);

#endif
